package com.zenithmind.disk.pojo.vo;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.zenithmind.disk.enums.FileStatus;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;

import java.time.LocalDateTime;

/**
 * 文件信息视图对象
 * 遵循单一职责原则：专注于文件数据展示
 * 遵循开闭原则：通过方法封装便于扩展
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(description = "文件信息VO")
public class FileVO {

    @Schema(description = "文件ID")
    private String id;

    @Schema(description = "用户ID")
    private String userId;

    @Schema(description = "父级目录ID")
    private String parentId;

    @Schema(description = "文件名")
    private String fileName;

    @Schema(description = "文件类型")
    private String fileType;

    @Schema(description = "文件大小（字节）")
    private Long fileSize;

    @Schema(description = "文件存储路径")
    private String filePath;

    @Schema(description = "是否为目录")
    private Boolean isDirectory;

    @Schema(description = "文件状态")
    private String fileStatus;

    @Schema(description = "是否加密")
    private Integer isEncrypted;

    @Schema(description = "创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime createTime;

    @Schema(description = "更新时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime updateTime;

    // ==================== 扩展字段 ====================

    @Schema(description = "格式化的文件大小")
    private String formattedFileSize;

    @Schema(description = "文件扩展名")
    private String fileExtension;

    @Schema(description = "文件图标类型")
    private String iconType;

    @Schema(description = "是否可预览")
    private Boolean canPreview;

    // ==================== 业务方法 ====================

    /**
     * 检查是否为目录
     * @return true如果是目录
     */
    public boolean isDirectoryType() {
        return Boolean.TRUE.equals(isDirectory);
    }

    /**
     * 检查是否为文件
     * @return true如果是文件
     */
    public boolean isFileType() {
        return !isDirectoryType();
    }

    /**
     * 检查是否在根目录
     * @return true如果在根目录
     */
    public boolean isInRootDirectory() {
        return StringUtils.isBlank(parentId);
    }

    /**
     * 检查是否加密
     * @return true如果加密
     */
    public boolean isEncryptedFile() {
        return isEncrypted != null && isEncrypted == 1;
    }

    /**
     * 获取文件扩展名
     * @return 文件扩展名，不包含点号
     */
    public String getFileExtension() {
        if (fileExtension != null) {
            return fileExtension;
        }

        if (StringUtils.isBlank(fileName) || isDirectoryType()) {
            return "";
        }

        int lastDotIndex = fileName.lastIndexOf('.');
        String extension = lastDotIndex > 0 ? fileName.substring(lastDotIndex + 1).toLowerCase() : "";
        this.fileExtension = extension;
        return extension;
    }

    /**
     * 获取格式化的文件大小
     * @return 格式化后的文件大小字符串
     */
    public String getFormattedFileSize() {
        if (formattedFileSize != null) {
            return formattedFileSize;
        }

        if (fileSize == null || fileSize <= 0 || isDirectoryType()) {
            this.formattedFileSize = "-";
            return formattedFileSize;
        }

        String[] units = {"B", "KB", "MB", "GB", "TB"};
        double size = fileSize.doubleValue();
        int unitIndex = 0;

        while (size >= 1024 && unitIndex < units.length - 1) {
            size /= 1024;
            unitIndex++;
        }

        this.formattedFileSize = String.format("%.2f %s", size, units[unitIndex]);
        return formattedFileSize;
    }

    /**
     * 获取文件图标类型
     * @return 文件图标类型
     */
    public String getIconType() {
        if (iconType != null) {
            return iconType;
        }

        if (isDirectoryType()) {
            this.iconType = "folder";
            return iconType;
        }

        String extension = getFileExtension();
        if (StringUtils.isBlank(extension)) {
            this.iconType = "file";
            return iconType;
        }

        // 根据文件扩展名确定图标类型
        switch (extension) {
            case "jpg":
            case "jpeg":
            case "png":
            case "gif":
            case "bmp":
            case "webp":
                this.iconType = "image";
                break;
            case "mp4":
            case "avi":
            case "mkv":
            case "mov":
            case "wmv":
            case "flv":
                this.iconType = "video";
                break;
            case "mp3":
            case "wav":
            case "flac":
            case "aac":
            case "ogg":
            case "wma":
                this.iconType = "audio";
                break;
            case "pdf":
                this.iconType = "pdf";
                break;
            case "doc":
            case "docx":
                this.iconType = "word";
                break;
            case "xls":
            case "xlsx":
                this.iconType = "excel";
                break;
            case "ppt":
            case "pptx":
                this.iconType = "powerpoint";
                break;
            case "txt":
            case "md":
                this.iconType = "text";
                break;
            case "zip":
            case "rar":
            case "7z":
            case "tar":
            case "gz":
                this.iconType = "archive";
                break;
            default:
                this.iconType = "file";
        }

        return iconType;
    }

    /**
     * 检查文件是否可预览
     * @return true如果可预览
     */
    public boolean canPreview() {
        if (canPreview != null) {
            return canPreview;
        }

        if (isDirectoryType()) {
            this.canPreview = false;
            return canPreview;
        }

        String extension = getFileExtension();
        if (StringUtils.isBlank(extension)) {
            this.canPreview = false;
            return canPreview;
        }

        // 可预览的文件类型
        String[] previewableExtensions = {
            "jpg", "jpeg", "png", "gif", "bmp", "webp", // 图片
            "txt", "md", "json", "xml", "html", "css", "js", // 文本
            "pdf" // PDF
        };

        for (String ext : previewableExtensions) {
            if (ext.equals(extension)) {
                this.canPreview = true;
                return canPreview;
            }
        }

        this.canPreview = false;
        return canPreview;
    }

    /**
     * 检查是否为图片文件
     * @return true如果是图片文件
     */
    public boolean isImageFile() {
        return "image".equals(getIconType());
    }

    /**
     * 检查是否为视频文件
     * @return true如果是视频文件
     */
    public boolean isVideoFile() {
        return "video".equals(getIconType());
    }

    /**
     * 检查是否为音频文件
     * @return true如果是音频文件
     */
    public boolean isAudioFile() {
        return "audio".equals(getIconType());
    }

    /**
     * 获取文件状态描述
     * @return 文件状态描述
     */
    public String getFileStatusDescription() {
        if (StringUtils.isBlank(fileStatus)) {
            return "未知";
        }

        try {
            FileStatus status = FileStatus.valueOf(fileStatus.toUpperCase());
            return status.getDescription();
        } catch (IllegalArgumentException e) {
            return fileStatus;
        }
    }

    /**
     * 获取创建时间的相对描述
     * @return 相对时间描述
     */
    public String getRelativeCreateTime() {
        if (createTime == null) {
            return "";
        }

        LocalDateTime now = LocalDateTime.now();
        java.time.Duration duration = java.time.Duration.between(createTime, now);

        long days = duration.toDays();
        long hours = duration.toHours();
        long minutes = duration.toMinutes();

        if (days > 0) {
            return days + "天前";
        } else if (hours > 0) {
            return hours + "小时前";
        } else if (minutes > 0) {
            return minutes + "分钟前";
        } else {
            return "刚刚";
        }
    }

    /**
     * 初始化扩展字段
     */
    public void initializeExtendedFields() {
        getFormattedFileSize();
        getFileExtension();
        getIconType();
        canPreview();
    }
}